#![allow(dead_code)]
pub struct Solution;

impl Solution {
    pub fn roman_to_int(s: String) -> i32 {
        // 1 = "I" 2 = "II" 3 = "III" 4 = "IV" 5 = "V" 6 = "VI" 7 = "VII" 8 = "VIII" 9 = "IX" 10 = "X"
        // 20 = "XX" 30 = "XXX" 40 = "XL" 50 = "L" 60 = "LX" 70 = "LXX" 80 = "LXXX" 90 = "XC" 100 = "C"
        //
        // NOTE: 算法：两数相比，前大后小，则当前数用+。前小后大，当前数用减。
        // - XXVII 可视作 X+X+V+I+I=10+10+5+1+1=27
        // - XXIV 可视作 X+X+I+V=10+10-1+5=24
        // - MCMXCIV 可视作 M+C+M+X+C+I+V=1000-100+1000-10+100-1+5=1994
        //
        fn get_value(char: char) -> i32 {
            match char {
                'I' => 1,
                'V' => 5,
                'X' => 10,
                'L' => 50,
                'C' => 100,
                'D' => 500,
                'M' => 1000,
                _ => panic!("invalid char"),
            }
        }
        // WARN: String 长度问题：
        // std::string::String::len -- pub fn len(&self)->usize 以字节为单位，而不是char或字素。pointer, slice, str, vec, HashMap, ...
        // chars().count()
        let len = s.chars().count();
        // 初始化总数
        let mut sum: i32 = 0;
        // #[allow(clippy::iter_nth_zero)]
        // 初始化第一个数
        // WARN: 字面量取值的问题：
        // str::chars -- pub fn chars(&self)->Chars<'_'> 返回字符串切片的char迭代器
        // std::iter::Iterator::nth -- pub fn nth(&mut self, n:usize)->Option<Self::Item> 返回迭代器的第n个元素
        // std::option::Option::unwrap -- pub fn unwrap(self)->T 将Option中的值取出。unwrap_or, unwrap_or_else, unwrap_or_default
        //
        // WARN: nth(0) 的问题:
        // 尽量采用next() 方法来迭代。
        let mut left_num = get_value(s.chars().next().expect("empty string"));
        // 从第二个数开始遍历
        for i in 1..len {
            // 获得下一个数
            // light_num 是一个临时变量
            let right_num = get_value(s.chars().nth(i).unwrap());
            // 比较下一个数：
            if left_num < right_num {
                // 如果后大，总数减去当前
                sum -= left_num;
            } else {
                // 如果后小，总数加上当前
                sum += left_num;
            }
            // 后替换前
            left_num = right_num;
        }
        sum += left_num;
        sum
    }
}

#[cfg(test)]
mod test_roman_to_int {
    use super::Solution;
    #[test]
    fn test_1() {
        assert_eq!(Solution::roman_to_int("I".to_string()), 1);
    }
    #[test]
    fn test_2() {
        assert_eq!(Solution::roman_to_int("IV".to_string()), 4);
    }
    #[test]
    fn test_3() {
        assert_eq!(Solution::roman_to_int("III".to_string()), 3);
    }
    #[test]
    fn test_4() {
        assert_eq!(Solution::roman_to_int("MCMXCIV".to_string()), 1994)
    }
}
